package zdc.display {
import com.greensock.TweenLite;

import flash.display.DisplayObject;
import flash.display.Graphics;
import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.TouchEvent;
import flash.geom.Point;
import flash.net.URLRequest;

import org.tuio.TuioTouchEvent;

import zdc.CollectionUtil;
import zdc.misc.Direction;
import zdc.ui.MovingInertia;
import zdc.Util;

/**
 *
 * @author Metal Slime
 */
public class SwipingSlider extends MovieClip {
    private var _firstAndLastSwipable:Boolean = false;
    private var _pages:Array = [];
    //缓动时间
    private var _tweenTime:Number = 0.3;
    //dist
    private var _minDx:Number = 0.2;
    private var _minDy:Number = 0.2;
    //方向
    private var _dir:String = "h";
    //尺寸
    protected var _wid:Number = 2560;
    protected var _hei:Number = 1080;

    protected var _tw:TweenLite;
    private var _curInd:uint = 0;
    protected var _lastInd:int = -1;
    protected var _mi:MovingInertia;
    protected var _handler:DisplayObject;

    protected var _pageBox:Sprite;
    protected var _space:Sprite;
    protected var _mask:Sprite;

    private var _mixTwObj:Object;

    private var _left:Boolean = false;
    private var _up:Boolean = false;

    private var _tweenable:Boolean = true;
    private var _swipable:Boolean = true;

    private var _offsetX:Number = 0;
    private var _offsetY:Number = 0;

    private var _createdHooks:Vector.<Function> = new Vector.<Function>();

    protected var _preLoadNum:int = 2;

    protected var _DOWN_EVT:String = TuioTouchEvent.TOUCH_DOWN;
    protected var _UP_EVT:String = TuioTouchEvent.TOUCH_UP;
    protected var _MOVE_EVT:String = TuioTouchEvent.TOUCH_MOVE;
    protected var _OUT_EVT:String = TuioTouchEvent.ROLL_OUT;


    protected var _movableCheckFun:Function;
    //protected var _DOWN_EVT:String;
    //protected var _UP_EVT:String;
    //protected var _MOVE_EVT:String;
    //protected var _OUT_EVT:String;

    public function SwipingSlider() {
        stage ? init() : addEventListener(Event.ADDED_TO_STAGE, init);
    }

    protected function init(e:Event = null):void {
        removeEventListener(Event.ADDED_TO_STAGE, init);
        addEventListener(Event.EXIT_FRAME, onExitFrame);
    }

    protected function onExitFrame(e:Event):void {
        removeEventListener(Event.EXIT_FRAME, onExitFrame);
        initVars();
        initState();
        initEvents();
        run();
    }

    protected function initVars():void {
        //trace("_minDx:", _minDx, "_minDy:", _minDy);
    }

    //图片容器
    protected function createImagesBox():void {
        _pageBox = new Sprite();
        addChild(_pageBox);
    }

    //创建占位
    private function createSpace():void {
        _space = new Sprite();
        var g:Graphics = _space.graphics;
        g.beginFill(0, 0);
        g.drawRect(0, 0, _wid, _hei);
        g.endFill();
        //this.addChild(_space);
    }

    //创建蒙版
    private function createMask():void {
        _mask = new Sprite();
        var g:Graphics = _mask.graphics;
        g.beginFill(0);
        g.drawRect(0, 0, _wid, _hei);
        g.endFill();
        //this.addChild(_mask);
    }

    //鼠标弹起
    private function onUp(e:Event, totalTime:Number, totalDx:Number, totalDy:Number):void {
        if (_mi.isH && Math.abs(totalDx) >= _minDx * _wid) {
            if (_mi.isRight) {
                if (_curInd > 0) {
                    _curInd--;
                }

            }
            else if (_mi.isLeft) {
                if (_curInd < _pages.length - 1) {
                    _curInd++;
                }
            }
        }
        else if (_mi.isV && Math.abs(totalDy) >= _minDy * _hei) {
            if (_mi.isDown) {
                if (_curInd > 0) {
                    _curInd--;
                }
            }
            else if (_mi.isUp) {
                if (_curInd < _pages.length - 1) {
                    _curInd++;
                }
            }
        }
        _left = _mi.isLeft;
        _up = _mi.isUp;
        _tweenable && tweenPage();
    }

    public function tweenPage():void {
        loadPage();
        _tw && _tw.kill();
        _tw = TweenLite.to(_pageBox, _tweenTime, Util.mix({
            x: (_mi.isH ? -_curInd * wid + _offsetX : _pageBox.x),
            y: (_mi.isV ? -_curInd * hei + _offsetY : _pageBox.y)
        }, _mixTwObj));
    }

    private function onMove(e:Event, dx:Number, dy:Number):void {
        if (_mi.isH) {			//trace((_pageBox.x + dx) > _offsetX, _pageBox.x + dx, offsetX);
            if (_curInd < 1 && dx > 0 && ((_pageBox.x + dx) > _offsetX)) {
                return;
            }
            else if (_curInd >= _pages.length - 1 && dx < 0 && ((_pageBox.x + dx) < -_curInd * wid + offsetX)) {
                return;
            }
            _pageBox.x += dx;
        }
        else if (_mi.isV) {
            _pageBox.y += dy;
        }
    }

    //鼠标按下
    private function onDown(e:Event):void {
        _tw && _tw.kill();
    }

    protected function initState():void {
        if (!_pageBox) {
            //Util.clearChildren(this);
            //createSpace();
            createImagesBox();
        }
        //createMask();
        //_pageBox.mask = _mask;

        _mi = new MovingInertia(_handler || _pageBox, _pageBox, _DOWN_EVT, _UP_EVT, _MOVE_EVT, _OUT_EVT, _dir);
        _mi.addDownHook(onDown);
        _mi.addMoveHook(onMove);
        _mi.addUpHook(onUp);
    }

    protected function setPages():void {
        _tw && _tw.kill();
        Util.clearChildren(_pageBox);
        _curInd = 0;
        loadPage();
    }

    //预加载前面和后面两张
    public function loadPage():void {
        //track("loadPage start", _curInd, _preLoadNum, _pages.length, (_curInd - _preLoadNum < _pages.length) && (_curInd <= _curInd + _preLoadNum));
        //for (var i:int = _curInd - _preLoadNum; i < _pages.length && _curInd <= _curInd + _preLoadNum; i++) {
        //track("OK");
        //track("_pages[i] is Class", _pages[i] is Class, _pages[i]);
        //如果已加载过，则跳过
        //if (i <= _lastInd || i < 0) {
        //continue;
        //}
        //track("OK2");
        //var currentDio:DisplayObject;
        //如果为图片路径
        //if (_pages[i] is String) {
        //var loader:Loader = new Loader();
        //loader.load(new URLRequest(_pages[i]));
        //loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoadComplete);
        //_pageBox.addChild(loader);
        //if (_mi.isH) {
        //loader.x = i * _wid;
        //}
        //else if (_mi.isV) {
        //loader.y = i * _hei;
        //}
        //loader.width = _wid;
        //loader.height = _hei;
        //currentDio = loader;
        //}
        //else if (_pages[i] is Class) {
        //var cdio:DisplayObject = new _pages[i]();		//trace("load:", _pages[i], _lastInd, i);
        //_pageBox.addChild(cdio);
        //if (_mi.isH) {
        //cdio.x = i * _wid;
        //}
        //else if (_mi.isV) {
        //cdio.y = i * _hei;
        //}
        //currentDio = cdio;
        //}
        //如果为显示对象
        //else {			 						track("OK3");
        //var dio:DisplayObject = _pages[i];
        //Util.rmChild(dio);
        //_pageBox.addChild(dio);
        //if (_mi.isH) {
        //dio.x = i * _wid;
        //}
        //else if (_mi.isV) {
        //dio.y = i * _hei;
        //}
        //currentDio = dio;
        //}
        //track("finished");
        //exeCreatedHook(currentDio, i);
        //_lastInd = Math.max(_lastInd, i);
        //}
        for (var i:int = 0; i < _pages.length; i++) {
            if (i <= _lastInd || i < 0) {
                continue;
            }

            var dio:DisplayObject = _pages[i];
            Util.rmChild(dio);
            _pageBox.addChild(dio);
            if (_mi.isH) {
                dio.x = i * _wid;
            }
            else if (_mi.isV) {
                dio.y = i * _hei;
            }
            exeCreatedHook(dio, i);
            _lastInd = Math.max(_lastInd, i);
            //track("create obj", i);
        }
        //track("create objs");
    }

    protected var _fun:Function;

    public function track(...msg):void {
        //_fun && _fun(msg);
    }

    /**
     * 执行所有创建后钩子
     * @param    dio
     * @param    index
     */
    private function exeCreatedHook(dio:DisplayObject, index:uint):void {
        for each(var hook:Function in _createdHooks) {
            hook(dio, index);
        }
    }

    /**
     * 添加创建后钩子
     * @param    hook
     */
    public function addCreatedHook(hook:Function):void {
        if (CollectionUtil.contains(_createdHooks, hook) > -1) {
            _createdHooks.push(hook);
        }
    }

    /**
     * 删除创建后钩子
     * @param    hook
     */
    public function removeCreatedHook(hook:Function):void {
        CollectionUtil.removeItems(_createdHooks, hook);
    }

    private function onLoadComplete(e:Event):void {
        var li:LoaderInfo = (e.currentTarget as LoaderInfo);
        li.removeEventListener(Event.COMPLETE, onLoadComplete);
        var l:Loader = li.loader;
        //var best:Point = Util.getRatioSize(l.content.width, l.content.height, _wid, _hei);
        //l.width = best.x;
        //l.height = best.y;
        l.width = _wid;
        l.height = _hei;
    }

    protected function initEvents():void {

    }

    protected function run():void {
    }

    /**
     * 获取某一页
     * @param    index
     * @return
     */
    public function getIndexedDisplayObject(index:uint):DisplayObject {
        if (index < _pageBox.numChildren) {
            return _pageBox.getChildAt(index);
        }
        return null;
    }

    /**
     * 跳到某一页
     * @param    index
     */
    public function goto(index:uint):void {
        _tw && _tw.kill();
        _curInd = index;
        loadPage();
        if (isH) {
            _pageBox.x = -_curInd * wid + _offsetX;
        }
        if (isV) {
            _pageBox.y = -_curInd * hei + _offsetY;
        }
    }

    /**
     * 当前共有多少页
     */
    public function get pages():Array {
        return _pages;
    }

    [Inspectable]
    public function set pages(value:Array):void {
        _pages = value;
    }

    public function get minDx():Number {
        return _minDx;
    }

    [Inspectable(defaultValue=0.3)]
    public function set minDx(value:Number):void {
        _minDx = value;
    }

    public function get minDy():Number {
        return _minDy;
    }

    [Inspectable(defaultValue=0.3)]
    public function set minDy(value:Number):void {
        _minDy = value;
    }

    public function get dir():String {
        return _dir;
    }

    [Inspectable(enumeration="h,v", defaultValue="h")]
    public function set dir(value:String):void {
        _dir = value;
        if (_mi) {
            _mi.dir = _dir;
        }
    }

    public function get tweenTime():Number {
        return _tweenTime;
    }

    [Inspectable(defaultValue="0.5")]
    public function set tweenTime(value:Number):void {
        _tweenTime = value;
    }

    public function get wid():Number {
        return _wid;
    }

    [Inspectable(defaultValue=1920)]
    public function set wid(value:Number):void {
        _wid = value;
    }

    public function get hei():Number {
        return _hei;
    }

    [Inspectable(defaultValue=1080)]
    public function set hei(value:Number):void {
        _hei = value;
    }

    public function get tweenable():Boolean {
        return _tweenable;
    }

    public function set tweenable(value:Boolean):void {
        _tweenable = value;
    }

    public function get swipable():Boolean {
        return _swipable;
    }

    public function set swipable(value:Boolean):void {
        _mi.enable = _swipable = value;
    }

    public function get left():Boolean {
        return _left;
    }

    public function get up():Boolean {
        return _up;
    }

    public function get isH():Boolean {
        return _mi.isH;
    }

    public function get isV():Boolean {
        return _mi.isV;
    }

    public function get curIndex():uint {
        return _curInd;
    }

    public function get pageNum():uint {
        return _pages.length;
    }


    public function get mixTwObj():Object {
        return _mixTwObj;
    }

    public function set mixTwObj(value:Object):void {
        _mixTwObj = value;
    }

    public function realse():void {

    }

    public function get hasNext():Boolean {
        return _curInd < _pages.length - 1;
    }

    public function get hasPrev():Boolean {
        return _curInd > 0;
    }

    public function get offsetX():Number {
        return _offsetX;
    }

    public function set offsetX(value:Number):void {
        _offsetX = value;
        _mask.x = _pageBox.x = _offsetX;
    }

    public function get offsetY():Number {
        return _offsetY;
    }

    public function set offsetY(value:Number):void {
        _offsetY = value;
        _mask.y = _pageBox.y = _offsetY;
    }

    public function get firstAndLastSwipable():Boolean {
        return _firstAndLastSwipable;
    }

    public function set firstAndLastSwipable(value:Boolean):void {
        _firstAndLastSwipable = value;
    }

    public function get preLoadNum():int {
        return _preLoadNum;
    }

    public function set preLoadNum(value:int):void {
        _preLoadNum = value;
    }

    public function get movableCheckFun():Function {
        return _movableCheckFun;
    }

    public function set movableCheckFun(value:Function):void {
        _mi.movableCheckFun = value;
        _movableCheckFun = value;
    }
}
}